﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Linq;
using System.IO;
using System.Globalization;
using System.Xml.Xsl;
using System.Xml;
using System.Text.RegularExpressions;
using System.Windows.Data;
using System.Globalization;

using ITunesSolver.Data;

namespace ITunesSolver.Helpers
{
    public class ITunesHelper
    {
        public static IEnumerable<Song> FindTop10Played(string fileName, HashSet<Song> songs)
        {
            if (songs == null) return null;

            var mySongs = from s in songs.AsParallel()
                          orderby s.PlayCount descending
                          select s;

            return mySongs;

            //Console.WriteLine(" Top 10 Most Played Songs:");
            //foreach (var s in mySongs.Take(10))
            //{
            //    Console.WriteLine(" {0}   {1} ({2})", s.PlayCount, s.Name, s.Artist);
            //}
        }

        public static List<string> GetITunesTrackKeys(string fileName)
        {
            var keys = from key in XDocument.Load(fileName).Descendants("plist").Elements("dict").Elements("dict").Elements("dict").Elements("key")
                       select (string)key;

            return keys.Distinct().ToList();
        }

        public static List<string> GetITunesPlaylistKeys(string fileName)
        {
            var playlistStart = XDocument.Load(fileName).Descendants("plist").Elements("dict").Elements("key").First(a => a.Value == "Playlists");
            var keys = from key in playlistStart.ElementsAfterSelf().Elements("dict").Elements("key")
                       select (string)key;

            return keys.Distinct().ToList();
        }

        public static void SaveITunesLibrary(string fileName, ITunesLibrary iTunesLibrary)
        {
            StreamWriter sw = File.CreateText(fileName);
            sw.WriteLine("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
            sw.WriteLine("<!DOCTYPE plist PUBLIC \"-//Apple Computer//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">");
            sw.WriteLine("<plist version=\"1.0\">");
            sw.WriteLine("<dict>");

            SaveMetaData(sw, iTunesLibrary.MetaData);
            SaveTracksToITunes(sw, iTunesLibrary.Songs);
            SavePlaylistsToITunes(sw, iTunesLibrary.Playlists);

            sw.WriteLine("</dict>");
            sw.WriteLine("</plist>");

            sw.Close();
        }

        private static void SaveMetaData(StreamWriter sw, MetaData metaData)
        {
            if (metaData == null) return;

            XElement xml =
                        new XElement("dict",
                                CreateFieldXML(metaData.MajorVersion, "integer", "Major Version", "integer"),
                                CreateFieldXML(metaData.MinorVersion, "integer", "Minor Version", "integer"),
                                CreateFieldXML(metaData.ApplicationVersion, "string", "Application Version", "string"),
                                CreateFieldXML(metaData.Features, "integer", "Features", "integer"),
                                CreateFieldXML(metaData.ShowContentRatings, "bool", "Show Content Ratings", "bool"),
                                CreateFieldXML(metaData.MusicFolder, "string", "Music Folder", "string"),
                                CreateFieldXML(metaData.LibraryPersistentId, "string", "Library Persistent ID", "string")
                                );

            XElement[] descendants = xml.Elements().ToArray();
            for (int k = 0; k < descendants.Count(); k += 2)
            {
                string key = descendants[k].ToString();
                string value = descendants[k + 1].ToString();
                sw.WriteLine("\t" + key + value);
            }
        }

        public static void SaveTracksToITunes(StreamWriter sw, HashSet<Song> songs)
        {
            if (songs == null) return;

            XElement xml =
                        new XElement("dict",
                       from s in songs.AsParallel()
                       select CreateSongXML(s));

            sw.WriteLine("\t<key>Tracks</key>");
            sw.WriteLine("\t<dict>");

            XElement[] descendants = xml.Elements().ToArray();
            for (int i = 0; i < descendants.Count(); i+=2)
            {
                string trackNumber = descendants[i].ToString();
                sw.WriteLine("\t\t" + trackNumber);
                XElement track = descendants[i + 1];
                sw.WriteLine("\t\t<dict>");

                XElement[] trackDescendants = track.Elements().ToArray();
                for (int j = 0; j < trackDescendants.Count(); j += 2)
                {
                    string key = trackDescendants[j].ToString();
                    string value = trackDescendants[j+1].ToString();
                    sw.WriteLine("\t\t\t" + key + value);
                }

                sw.WriteLine("\t\t</dict>");
            }

            sw.WriteLine("\t</dict>");
        }

        public static void SavePlaylistsToITunes(StreamWriter sw, HashSet<Playlist> playlists)
        {
            if (playlists == null) return;

            XElement xml =
                        new XElement("dict",
                       from p in playlists.AsParallel()
                       select CreatePlaylistXML(p));

            sw.WriteLine("\t<key>Playlist Items</key>");
            sw.WriteLine("\t<array>");

            XElement[] descendants = xml.Elements().ToArray();
            for (int i = 0; i < descendants.Count(); i++)
            {
                XElement playlist = descendants[i];
                sw.WriteLine("\t\t<dict>");

                XElement[] playlistDescendants = playlist.Elements().ToArray();
                for (int j = 0; j < playlistDescendants.Count(); j += 2)
                {
                    if (playlistDescendants[j].Name == "array")
                    {
                        sw.WriteLine("\t\t\t<key>Playlist Items</key>");
                        sw.WriteLine("\t\t\t<array>");

                        XElement[] tracks = playlistDescendants[j].Elements("dict").Elements().ToArray();
                        for (int k = 0; k < tracks.Count(); k += 2)
                        {
                            string key = tracks[k].ToString();
                            string value = tracks[k + 1].ToString();
                            sw.WriteLine("\t\t\t\t<dict>");
                            sw.WriteLine("\t\t\t\t\t" + key + value);
                            sw.WriteLine("\t\t\t\t</dict>");
                        }

                        sw.WriteLine("\t\t\t</array>");
                    }
                    else
                    {
                        string key = playlistDescendants[j].ToString();
                        string value = playlistDescendants[j + 1].ToString();
                        if (playlistDescendants[j + 1].Name == "data")
                        {
                            sw.WriteLine("\t\t\t" + key);
                            sw.WriteLine("\t\t\t" + value);
                        }
                        else
                        {
                            sw.WriteLine("\t\t\t" + key + value);
                        }
                    }
                }

                sw.WriteLine("\t\t</dict>");
            }

            sw.WriteLine("\t</array>");
        }

        private static XElement[] CreatePlaylistXML(Playlist playlist)
        {
            XElement[] xElArr = new XElement[1];
            XElement xEl1 = new XElement("dict",
                CreateFieldXML(playlist.Name, "string", "Name", "string"),
                CreateFieldXML(playlist.Master, "bool", "Master", "bool"),
                CreateFieldXML(playlist.PlaylistId, "integer", "Playlist ID", "integer"),
                CreateFieldXML(playlist.PersistentId, "string", "Playlist Persistent ID", "string"),
                CreateFieldXML(playlist.Visible, "bool", "Visible", "bool"),
                CreateFieldXML(playlist.AllItems, "bool", "All Items", "bool"),
                //CreateSongFieldXML(playlist.Items, "integer", "Playlist Items", "integer"),
                CreateFieldXML(playlist.DistinguishedKind, "integer", "Distinguished Kind", "integer"),
                CreateFieldXML(playlist.Music, "bool", "Music", "bool"),
                CreateFieldXML(playlist.SmartInfo, "string", "Smart Info", "data"),
                CreateFieldXML(playlist.SmartCriteria, "string", "Smart Criteria", "data"),
                CreateFieldXML(playlist.Movies, "bool", "Movies", "bool"),
                CreateFieldXML(playlist.TVShows, "bool", "TV Shows", "bool"),
                CreateFieldXML(playlist.Podcasts, "bool", "Podcasts", "bool"),
                CreateFieldXML(playlist.PurchasedMusic, "bool", "Purchased Music", "bool"),
                CreateFieldXML(playlist.PartyShuffle, "bool", "Party Shuffle", "bool"),
                
                CreateFieldXML(playlist.Items)

                    //CreateSongFieldXML(s.debug, "string", "debug", "string")

                );

            xElArr[0] = xEl1;

            return xElArr;
        }

        private static void TransformXElementAndSave(XElement xml, string xsl, string fileName)
        {
            XslCompiledTransform transform = new XslCompiledTransform();
            transform.Load(xsl);

            using (XmlReader r = xml.CreateReader())
            using (XmlTextWriter w = new XmlTextWriter(fileName, Encoding.Default))
            {
                w.Formatting = Formatting.None;
                transform.Transform(r, w);

                XmlDocument doc = new XmlDocument();
                doc.Save(w);
            }
            

        }

        private static XElement[] CreateSongXML(Song s)
        {
            XElement[] xElArr = new XElement[2];
            XElement xEl1 = new XElement("key", s.TrackId);
            XElement xEl2 = new XElement("dict",
                CreateFieldXML(s.TrackId, "integer", "Track ID", "integer"),
                CreateFieldXML(s.Name, "string", "Name", "string"),
                CreateFieldXML(s.Artist, "string", "Artist", "string"),
                CreateFieldXML(s.AlbumArtist, "string", "Album Artist", "string"),
                CreateFieldXML(s.Album, "string", "Album", "string"),
                CreateFieldXML(s.Genre, "string", "Genre", "string"),
                CreateFieldXML(s.Kind, "string", "Kind", "string"),
                CreateFieldXML(s.Size, "integer64", "Size", "integer"),
                CreateFieldXML(s.TotalTime, "integer64", "Total Time", "integer"),
                CreateFieldXML(s.DiscNumber, "integer", "Disk Number", "integer"),
                CreateFieldXML(s.DiscCount, "integer", "Disk Count", "integer"),
                CreateFieldXML(s.TrackNumber, "integer", "Track Number", "integer"),
                CreateFieldXML(s.TrackCount, "integer", "Track Count", "integer"),
                CreateFieldXML(s.Year, "integer", "Year", "integer"),
                CreateFieldXML(s.DateModified, "date", "Date Modified", "date"),
                CreateFieldXML(s.DateAdded, "date", "Date Added", "date"),
                CreateFieldXML(s.BitRate, "integer", "Bit Rate", "integer"),
                CreateFieldXML(s.SampleRate, "integer", "Sample Rate", "integer"),
                CreateFieldXML(s.PlayCount, "integer", "Play Count", "integer"),
                CreateFieldXML(s.PlayDate, "integer64", "Play Date", "integer"),
                CreateFieldXML(s.PlayDate_UTC, "date", "Play Date UTC", "date"),
                CreateFieldXML(s.RelaseDate, "date", "Release Date", "date"),

                CreateFieldXML(s.Comments, "string", "Comments", "string"),
                CreateFieldXML(s.Composer, "string", "Composer", "string"),
                CreateFieldXML(s.Location, "string", "Location", "string"),
                CreateFieldXML(s.CleanedLocation, "string", "Cleaned Location", "string"),
                CreateFieldXML(s.CleanedName, "string", "Cleaned Name", "string"),
                CreateFieldXML(s.CleanedArtist, "string", "Cleaned Artist", "string"),
                CreateFieldXML(s.CleanedAlbum, "string", "Cleaned Album", "string"),
                CreateFieldXML(s.Rating, "integer", "Rating", "integer"),
                CreateFieldXML(s.AlbumRating, "integer", "Album Rating", "integer"),
                CreateFieldXML(s.AlbumRatingComputed, "bool", "Album Rating Computed", "bool"),
                CreateFieldXML(s.PersistentID, "string", "Persistent ID", "string"),
                CreateFieldXML(s.TrackType, "string", "Track Type", "string"),
                CreateFieldXML(s.FileFolderCount, "integer", "File Folder Count", "integer"),
                CreateFieldXML(s.LibraryFolderCount, "integer", "Library Folder Count", "integer"),
                CreateFieldXML(s.ArtworkCount, "integer", "Artwork Count", "integer"),
                CreateFieldXML(s.Protected, "bool", "Protected", "bool"),
                CreateFieldXML(s.Purchased, "bool", "Purchased", "bool"),
                CreateFieldXML(s.SortAlbumArtist, "string", "Sort Album Artist", "string"),
                CreateFieldXML(s.SortArtist, "string", "Sort Artist", "string"),
                CreateFieldXML(s.Compilation, "bool", "Compilation", "bool"),
                CreateFieldXML(s.SortName, "string", "Sort Name", "string"),
                CreateFieldXML(s.SortAlbum, "string", "Sort Album", "string"),
                CreateFieldXML(s.SortComposer, "string", "Sort Composer", "string")
                //CreateSongFieldXML(s.debug, "string", "debug", "string")
            );

            xElArr[0] = xEl1;
            xElArr[1] = xEl2;

            return xElArr;
        }

        private static XElement CreateFieldXML(List<PlaylistItem> playlistItems)
        {
            if (playlistItems == null) return null;

            XElement playlistItemsXml =
                        new XElement("array",
                        new XElement("dict",
                       from p in playlistItems.AsParallel()
                       select CreateFieldXML(p.TrackId, "integer", "Track ID", "integer")));

            return playlistItemsXml;
        }

        private static XElement[] CreateFieldXML(object data, string dataType, string fieldName, string fieldType)
        {
            if (data == null) return null;

            string dataString = string.Empty;

            XElement[] xElArr = new XElement[2];
            XElement xEl1 = new XElement("key", fieldName);
            XElement xEl2 = null;

            try
            {
                switch (dataType)
                {
                    case "date":
                        if ((DateTime)data == DateTime.MinValue) return null;

                        dataString = ((DateTime)data).ToUniversalTime().ToString("yyyy-MM-ddTHH:mm:ssZ");
                        xEl2 = new XElement(fieldType, dataString);
                        break;
                    case "bool":
                        if (!((bool?)data).HasValue) return null;
                        dataString = ((bool?)data).Value.ToString().ToLower();
                        xEl2 = new XElement(dataString);
                        break;
                    case "integer":
                        if ((int)data == int.MinValue) return null;
                        dataString = data.ToString();
                        xEl2 = new XElement(fieldType, dataString);
                        break;
                    case "integer64":
                        if ((Int64)data == Int64.MinValue) return null;
                        dataString = data.ToString();
                        xEl2 = new XElement(fieldType, dataString);
                        break;
                    case "string":
                        dataString = data.ToString();
                        if (dataString == string.Empty) return null;
                        dataString = data.ToString();
                        xEl2 = new XElement(fieldType, dataString);
                        break;
                    default:
                        dataString = data.ToString();
                        xEl2 = new XElement(fieldType, dataString);
                        break;
                }
            }
            catch (Exception ex)
            {

            }

            xElArr[0] = xEl1;
            xElArr[1] = xEl2;

            return xElArr;
        }

        public static bool LoadITunesLibrary(ITunesLibrary iTunesLibrary)
        {
            if (iTunesLibrary.FileName != string.Empty)
            {
                XDocument xDoc = XDocument.Load(iTunesLibrary.FileName);
                iTunesLibrary.MetaData = LoadMetaDataFromITunes(xDoc);
                iTunesLibrary.Songs = LoadSongsFromITunes(xDoc);
                iTunesLibrary.Playlists = LoadPlaylistsFromITunes(xDoc);

                return true;
            }

            return false;
        }

        public static MetaData LoadMetaDataFromITunes(XDocument xDoc)
        {
            var rawMetaData = from key in xDoc.Descendants("plist").Elements("dict").Elements("key")
                                  .Where(a => !((string)a == "Tracks" || (string)a == "Playlists"))
                                  select new KeyValuePair<string, object>(((string)key).Replace(" ", ""), GetOriginalData((XElement)key.NextNode));


            MetaData metaData = new MetaData()
            {
                ApplicationVersion = rawMetaData.First(a => a.Key == "ApplicationVersion").Value.ToString(),
                Features = int.Parse(rawMetaData.First(a => a.Key == "Features").Value.ToString()),
                LibraryPersistentId = rawMetaData.First(a => a.Key == "LibraryPersistentID").Value.ToString(),
                MajorVersion = int.Parse(rawMetaData.First(a => a.Key == "MajorVersion").Value.ToString()),
                MinorVersion = int.Parse(rawMetaData.First(a => a.Key == "MinorVersion").Value.ToString()),
                MusicFolder = rawMetaData.First(a => a.Key == "MusicFolder").Value.ToString(),
                ShowContentRatings = (rawMetaData.First(a => a.Key == "ShowContentRatings").Value.ToString() == "true")
            };

            return metaData;
        }

        public static HashSet<Song> LoadSongsFromITunes(XDocument xDoc)
        {
            HashSet<Song> songs = null;

            try
            {
                var rawsongs = from song in xDoc.Descendants("plist").Elements("dict").Elements("dict").Elements("dict")
                               select new XElement("song",
                                   from key in song.Descendants("key")
                                   select new XElement(((string)key).Replace(" ", ""),
                                       GetOriginalData((XElement)key.NextNode)));

                var songList = rawsongs.Select((s, index) =>
                            new Song()
                            {
                                Index = index,
                                TrackId = s.Element("TrackID").ToInt(int.MinValue),
                                Album = s.Element("Album").ToString(string.Empty),
                                Artist = s.Element("Artist").ToString(string.Empty),
                                BitRate = s.Element("BitRate").ToInt(int.MinValue),
                                Comments = s.Element("Comments").ToString(string.Empty),
                                Composer = s.Element("Composer").ToString(string.Empty),
                                Genre = s.Element("Genre").ToString(string.Empty),
                                Kind = s.Element("Kind").ToString(string.Empty),
                                Location = s.Element("Location").ToString(string.Empty),
                                Name = s.Element("Name").ToString(string.Empty),
                                PlayCount = s.Element("PlayCount").ToInt(int.MinValue),
                                SampleRate = s.Element("SampleRate").ToInt(int.MinValue),
                                Size = s.Element("Size").ToInt64(int.MinValue),
                                TotalTime = s.Element("TotalTime").ToInt64(Int64.MinValue),
                                TrackNumber = s.Element("TrackNumber").ToInt(int.MinValue),
                                TrackCount = s.Element("TrackCount").ToInt(int.MinValue),
                                AlbumArtist = s.Element("AlbumArtist").ToString(string.Empty),
                                DateModified = DateTime.ParseExact(s.Element("DateModified").ToString(DateTime.MinValue.ToUniversalTime().ToString("yyyy-MM-ddTHH:mm:ssZ")), "yyyy-MM-ddTHH:mm:ssZ", CultureInfo.InvariantCulture),
                                DateAdded = DateTime.ParseExact(s.Element("DateAdded").ToString(DateTime.MinValue.ToUniversalTime().ToString("yyyy-MM-ddTHH:mm:ssZ")), "yyyy-MM-ddTHH:mm:ssZ", CultureInfo.InvariantCulture),
                                PlayDate = s.Element("PlayDate").ToInt64(Int64.MinValue),
                                PlayDate_UTC = DateTime.ParseExact(s.Element("PlayDateUTC").ToString(DateTime.MinValue.ToUniversalTime().ToString("yyyy-MM-ddTHH:mm:ssZ")), "yyyy-MM-ddTHH:mm:ssZ", CultureInfo.InvariantCulture),
                                Rating = s.Element("Rating").ToInt(int.MinValue),
                                AlbumRating = s.Element("AlbumRating").ToInt(int.MinValue),
                                AlbumRatingComputed = s.Element("AlbumRatingComputed").ToBool(null),
                                PersistentID = s.Element("PersistentID").ToString(string.Empty),
                                TrackType = s.Element("TrackType").ToString(string.Empty),
                                FileFolderCount = s.Element("FileFolderCount").ToInt(int.MinValue),
                                LibraryFolderCount = s.Element("LibraryFolderCount").ToInt(int.MinValue),
                                DiscNumber = s.Element("DiscNumber").ToInt(int.MinValue),
                                DiscCount = s.Element("DiscCount").ToInt(int.MinValue),
                                Year = s.Element("Year").ToInt(int.MinValue),
                                RelaseDate =  DateTime.ParseExact(s.Element("ReleaseDate").ToString(DateTime.MinValue.ToUniversalTime().ToString("yyyy-MM-ddTHH:mm:ssZ")), "yyyy-MM-ddTHH:mm:ssZ", CultureInfo.InvariantCulture),

                                ArtworkCount = s.Element("ArtworkCount").ToInt(int.MinValue),
                                Protected = s.Element("Protected").ToBool(null),
                                Purchased = s.Element("Purchased").ToBool(null),
                                SortAlbumArtist = s.Element("SortAlbumArtist").ToString(string.Empty),
                                SortArtist = s.Element("SortArtist").ToString(string.Empty),
                                Compilation = s.Element("Compilation").ToBool(null),
                                SortName = s.Element("SortName").ToString(string.Empty),
                                SortAlbum = s.Element("SortName").ToString(string.Empty),
                                SortComposer = s.Element("SortName").ToString(string.Empty),

                                CleanedLocation = GetCleanedLocation(s.Element("Location").ToString(string.Empty)),
                                CleanedName = GetCleanedName(s.Element("Name").ToString(string.Empty)),
                                CleanedArtist = GetCleanedArtist(s.Element("Artist").ToString(string.Empty)),
                                CleanedAlbum = GetCleanedAlbum(s.Element("Album").ToString(string.Empty)),

                                //debug = s.Element("PlayDateUTC").ToString(string.Empty)
                            });
                songs = songList.OrderBy(s => s.CleanedLocation).ToHashSet();
            }
            catch (Exception ex)
            {
            }

            return songs;
        }



        public static HashSet<Playlist> LoadPlaylistsFromITunes(XDocument xDoc)
        {
            HashSet<Playlist> playlists = null;

            try
            {
                var playlistStart = xDoc.Descendants("plist").Elements("dict").Elements("key").First(a => a.Value == "Playlists");
                var rawplaylists = from playlist in playlistStart.ElementsAfterSelf().Elements("dict")
                               select new XElement("playlist",
                                   from key in playlist.Elements("key")
                                   select new XElement(((string)key).Replace(" ", ""),
                                       GetOriginalData((XElement)key.NextNode)));

                var playlistList = rawplaylists.Select((p, index) =>
                            new Playlist()
                            {
                                Index = index,
                                PlaylistId = p.Element("PlaylistID").ToInt(int.MinValue),
                                Master = p.Element("Master").ToBool(null),
                                Name = p.Element("Name").ToString(string.Empty),
                                PersistentId = p.Element("PlaylistPersistentID").ToString(string.Empty),
                                DistinguishedKind = p.Element("DistinguishedKind").ToInt(null),
                                Music = p.Element("Music").ToBool(null),
                                AllItems = p.Element("AllItems").ToBool(null),
                                SmartInfo = p.Element("SmartInfo").ToString(string.Empty),
                                SmartCriteria = p.Element("SmartCriteria").ToString(string.Empty),
                                Movies = p.Element("Movies").ToBool(null),
                                TVShows = p.Element("TVShows").ToBool(null),
                                Podcasts = p.Element("Podcasts").ToBool(null),
                                PurchasedMusic = p.Element("PurchasedMusic").ToBool(null),
                                PartyShuffle = p.Element("PartyShuffle").ToBool(null),

                                Visible = p.Element("Visible").ToBool(null),
                                Items = LoadPlaylistItemsFromItunes(p.Element("PlaylistItems")),

                                

                                //debug = s.Element("PlayDateUTC").ToString(string.Empty)
                            });
                playlists = playlistList.ToHashSet();
            }
            catch (Exception ex)
            {
            }

            return playlists;
        }

        private static List<PlaylistItem> LoadPlaylistItemsFromItunes(XElement xElement)
        {
            if (xElement == null || xElement.Elements() == null) return null;

            var rawplaylistItems = from trackId in xElement.Elements("TrackID")
                               select new PlaylistItem()
                               {
                                   TrackId = int.Parse(trackId.Value)
                               };

            return rawplaylistItems.ToList();
        }


        
        private static object GetOriginalData(XElement xElement)
        {
            try
            {
                if (xElement.Name == "array")
                {
                    return GetOriginalPlaylistData(xElement.Descendants("dict"));
                }

                if (xElement.Name == "true" || xElement.Name == "false") return xElement.Name.ToString();

                return xElement.Value.ToString();
            }
            catch (Exception ex)
            {
            }

            return string.Empty;
        }

        private static IEnumerable<XElement> GetOriginalPlaylistData(IEnumerable<XElement> tracks)
        {
            if (tracks == null || tracks.Elements() == null) return null;

            var rawplaylisttracks = from key in tracks.Elements("key")
                                   select new XElement(((string)key).Replace(" ", ""),
                                       GetOriginalData((XElement)key.NextNode));

            return rawplaylisttracks;
        }

        static MatchCollection driveMatches;
        static string drivePattern = @"[A-Za-z][:][\\/]";
        static Regex driveRegex = new Regex(drivePattern, RegexOptions.IgnoreCase | RegexOptions.Compiled);

        static MatchCollection garbageMatches;
        static string garbagePattern = @"[0-9]*[ \~\`\=\+\|\,\.\<\>\?\{\}\'\:\;\|\]\[\-\(\)\!\@\#\$\%\^\&\*]?";
        static Regex garbageRegex = new Regex(garbagePattern, RegexOptions.IgnoreCase | RegexOptions.Compiled);

        public static string GetCleanedLocation(string location)
        {
            if (location == null) return string.Empty;
            if (!location.ToLower().Contains("file://localhost/")) return location;

            location = location.Replace("file://localhost/", "");
            location = driveRegex.Replace(location, "");

            int musicIndex = location.ToLower().LastIndexOf("music/");
            if (musicIndex == -1)
            {
                location = garbageRegex.Replace(location, "");
                return location;
            }
            location = location.Substring(musicIndex + 6);
            location = garbageRegex.Replace(location, "");

            //driveMatches = driveRegex.Matches(location);
            //for (int i = 0; i < driveMatches.Count; i++)
            //{
            //    location = location.Replace(driveMatches[i].Value, "");
            //}

            return location;
        }

        public static string GetCleanedName(string name)
        {
            if (name == null) return string.Empty;

            name = name.ToLower().Trim();
            name = name.Replace("the", "");
            name = name.Replace("&", "and");
            name = name.Replace("    ", " ");
            name = name.Replace("   ", " ");
            name = name.Replace("  ", " ");

            name = garbageRegex.Replace(name, "");

            name = name.Trim();

            return name;
        }

        public static string GetCleanedArtist(string artist)
        {
            if (artist == null) return string.Empty;

            artist = artist.ToLower().Trim();
            artist = artist.Replace("the", "");
            artist = artist.Replace("&", "and");
            artist = artist.Replace("    ", " ");
            artist = artist.Replace("   ", " ");
            artist = artist.Replace("  ", " ");

            artist = garbageRegex.Replace(artist, "");

            artist = artist.Trim();

            return artist;
        }

        public static string GetCleanedAlbum(string album)
        {
            if (album == null) return string.Empty;

            album = album.ToLower().Trim();
            album = album.Replace("the", "");
            album = album.Replace("&", "and");
            album = album.Replace("    ", " ");
            album = album.Replace("   ", " ");
            album = album.Replace("  ", " ");

            album = garbageRegex.Replace(album, "");

            album = album.Trim();

            return album;
        }
    }

    public class GetCleanedLocation : IValueConverter
    {
        private string originalValue;
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            originalValue = (value != null) ? value.ToString() : string.Empty;
            return ITunesHelper.GetCleanedLocation(originalValue);
        }

        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            return originalValue;
        }
    }
}
